<?php
/**
 * This is interface for storage via Amazon S3 storage engine
 * @package     nuo
 * @subpackage  nuo.storage
 * @author      Nam Nguyen <nam.ngvan@gmail.com>
 * @version     1.0
 * @since       Apr 19, 2013
 */
class Nuo_Storage_S3 extends Nuo_Storage_Abstract
{
	protected $_key = '';

	protected $_secret = '';

	protected $_bucket = '';

	protected $_streamWrapper;

	protected $_s3;

	protected $_region = '';

	protected $_isSSL = FALSE;

	protected $_endpoint = 's3.amazonaws.com';

	/**
	 * constructor
	 * @param array $config
	 */
	public function __construct($config)
	{
		extract($config, EXTR_SKIP);

		/**
		 * WARNING: please do not change orther of following code.
		 */
		$this -> setId($id);
		$this -> setSecret($secret);

		$this -> setBucket($bucket);

		$this -> setKey($key);
		$this -> setRegion($region);
		$this -> setIsSSL($ssl);

		$this -> setBaseUrl($baseUrl);
		$this -> setBasePath($basePath);

		if ($config['baseUrl'])
		{
			$this -> _baseUrl = 'http://' . $this -> _bucket . '.s3.amazonaws.com/';
		}
		else
		{
			$this -> _baseUrl = rtrim($config['baseUrl'], '/') . '/';
		}

		$this -> _basePath = rtrim($this -> _bucket . '/' . $path, '/') . '/';
	}

	/**
	 * @param bool $flag
	 * @return Storage_S3
	 */
	public function setIsSSL($flag)
	{
		$this -> _isSSL = (bool)$flag;
		return $this;
	}

	/**
	 * @return bool
	 */
	public function getIsSSL()
	{
		return $this -> _isSSL;
	}

	/**
	 * @param string $key
	 * @return Storage_S3
	 */
	public function setKey($key)
	{
		$this -> _key = $key;
		return $this;
	}

	/**
	 * @return string
	 */
	public function getKey()
	{
		return $this -> _key;
	}

	/**
	 * @param string $secret
	 * @return Storage_S3
	 */
	public function setSecret($secret)
	{
		$this -> _secret = $key;
		return $this;
	}

	/**
	 * @return string
	 */
	public function getSecret()
	{
		return $this -> _secret;
	}

	/**
	 * @param string $bucket
	 * @return Storage_S3
	 */
	public function setBucket($bucket)
	{
		$this -> _bucket = $bucket;
		return $this;
	}

	/**
	 * @return string
	 */
	public function getBucket()
	{
		return $this -> _bucket;
	}

	/**
	 * @param string $region
	 * @return Storage_S3
	 */
	public function setRegion($region)
	{
		$this -> _region = $region;
		return $this;
	}

	/**
	 * @return string
	 */
	public function getRegion()
	{
		return $this -> _region;
	}

	/**
	 * end point url
	 * @return string
	 */
	public function getEndpoint()
	{
		return $this -> _endpoint;
	}

	/**
	 * create s3 object
	 * @return S3
	 */
	function getS3()
	{
		if (null == $this -> _s3)
		{
			require_once LEGACY_DIR. 'storage/S3.php';
			
			$this -> _s3 = new S3($this -> _key, $this -> _secret, $this -> _ssl, $this -> _endpoint);
		}
		return $this -> _s3;
	}

	/**
	 * @param string $path
	 * @param string $local local file name to put
	 * @return bool
	 * @throws Exception
	 */
	function get($path, $local)
	{
		self::_makeLocalDir(dirname($local));

		$remote = $this -> getPath($path);

		if (!$this -> getS3() -> getObject($this -> _bucket, $remote, $local))
		{
			throw new Exception('could not get {from} to s3 {to}', array(
				'{from}' => $remote,
				'{to}' => $local
			));
		}
		return TRUE;
	}

	/**
	 * @param string $path
	 * @param string $local local file name
	 * @return bool
	 * @throws Exception
	 */
	public function put($path, $local)
	{
		$remote = $this -> getPath($path);

		if (!$this -> getS3() -> putObjectFile($local, $this -> _sBucket, $remote, S3::ACL_PUBLIC_READ))
		{
			throw new Exception('could not put {from} to s3 {to}', array(
				'{from}' => $local,
				'{to}' => $remote
			));
		}
		return TRUE;
	}

	/**
	 * get content of remote file
	 * @param string $path
	 * @return string
	 * @throws Exception
	 */
	function getContents($path)
	{
		$remote = $this -> getPath($path);

		$data = $this -> getS3() -> getObject($this -> _bucket, $remote, FALSE);

		if ($data === FALSE)
		{
			throw new Exception('File {file} does not exists!', array('{file}' => $path));
		}
		return $data;
	}

	/**
	 * put content to remote object
	 * @param string $path
	 * @param string $data data content to put
	 * @return bool
	 * @throws Exception
	 */
	function putContents($path, $data)
	{
		$remote = $this -> getPath($path);

		if (!$this -> getS3() -> putObject($data, $this -> _bucket, $remote, S3::ACL_PUBLIC_READ))
		{
			throw new Exception(strtr('could not put data to s3 {to}', array('{to}' => $remote)));
		}
		return TRUE;
	}

	/**
	 * delete remote file
	 * @param tring $path
	 * @return bool
	 * @throws Exception
	 */
	function delete($path)
	{
		$remote = $this -> getPath($path);

		if (!$this -> _oObject -> deleteObject($this -> _sBucket, $remote))
		{
			throw new Exception('Could not delete ' . $remote);
		}
		return TRUE;
	}

}
